import { Inject, Injectable } from '@nestjs/common';
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { PaginationDto } from 'src/common/dto/pagination.dto';
import { ToolsService } from 'src/utils/tools.service';
import { Brackets, DataSource, In } from 'typeorm';
import { Repository } from 'typeorm/repository/Repository';
import { TagEntity } from '../tag/entities/tag.entity';
import { UsersEntity } from '../user/entities/user.entity';
import { AddTagDto } from './dto/add-tag.dto';
import { CreateEssayDto } from './dto/create-essay.dto';
import { UpdateEssayDto } from './dto/update-essay.dto';
import { EssayEntity } from './entities/essay.entity';
import { v4 as uuidv4 } from 'uuid';
import * as moment from 'moment';
import { Cache } from 'cache-manager';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { RedisCacheService } from 'src/component/redis/redis-cache.service';
import { count } from 'console';

@Injectable()
export class EssayService {
  @InjectRepository(EssayEntity)
  private readonly essayRepository: Repository<EssayEntity>;

  @InjectDataSource()
  private readonly dataSource: DataSource;

  constructor(
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
    private readonly redisService: RedisCacheService,
  ) {}

  /**
   * 创建短文需要添加作者
   * @param createEssayDto
   * @param userid
   */
  async create(createEssayDto: CreateEssayDto, userid: string) {
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect(); //使用我们的新queryRunner建立真正的数据库连
    await queryRunner.startTransaction();

    try {
      // 清除整个缓存
      await this.cacheManager.reset();
      const user = await this.dataSource
        .getRepository(UsersEntity)
        .createQueryBuilder('user', queryRunner)
        .where('user.id = :id', {
          id: userid,
        })
        .getOne();
      if (!user) {
        throw new Error('用户不存在');
      }
      const id = uuidv4();
      await this.dataSource
        .getRepository(EssayEntity)
        .createQueryBuilder('essay', queryRunner)
        .insert()
        .into(EssayEntity)
        .values({
          id: id,
          essaytitle: createEssayDto.essaytitle,
          content: createEssayDto.content,
          user: user,
          created_at: moment().format('YYYY-MM-DD HH:mm:ss'),
        })
        .execute();
      await queryRunner.commitTransaction(); //提交事务
      return id;
    } catch (error) {
      await queryRunner.rollbackTransaction(); //出错回滚
      ToolsService.fail(error);
    } finally {
      await queryRunner.release(); //释放
    }
  }
  /**
   * 获取所有短文
   * @param essaytitle
   * @param pagination
   * @returns
   */
  async findAll(
    essaytitle: string,
    tagId: string,
    pagination: PaginationDto,
    userId: string,
  ) {
    try {
      let cacheKey = `EssayService_findAll_${essaytitle}_${tagId}_${pagination.currentPage}_${pagination.pageSize}_${userId}`;
      // 获取缓存
      const cacheData = await this.cacheManager.get(cacheKey);
      if (cacheData) {
        console.log(`${cacheKey}有缓存`);
        return cacheData;
      } else {
        console.log(`${cacheKey}没有缓存`);
        // 添加缓存
        const res = await this.dataSource
          .getRepository(EssayEntity)
          .createQueryBuilder('essay')
          .setParameters({
            param: '%' + essaytitle + '%',
          })
          .where('essay.essaytitle LIKE :param and essay.del = 0')
          .orderBy({ 'essay.status': 'DESC' }) //DESC ASC
          .addOrderBy('essay.created_at', 'DESC')
          .skip(pagination.currentPage * pagination.pageSize)
          .take(pagination.pageSize)
          .leftJoinAndSelect('essay.tags', 'tags')
          .andWhere(
            new Brackets((qb) => {
              if (!!tagId) {
                return qb.where(`tags.id = '${tagId}'`);
              } else {
                return qb;
              }
            }),
          )
          .leftJoin('essay.user', 'user')
          .andWhere('user.id = :id', { id: userId })
          .select(['essay', 'user', 'tags'])
          .getManyAndCount();

        // 添加缓存
        await this.cacheManager.set(cacheKey, res, 1000 * 60 * 60);

        return res;
      }
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  /**
   * 查询所有软删除的数据
   * @param essaytitle
   * @param pagination
   * @param userid
   * @returns
   */
  async findAllRecyclingStation(
    essaytitle: string,
    pagination: PaginationDto,
    userid: string,
  ) {
    try {
      const res = await this.dataSource
        .getRepository(EssayEntity)
        .createQueryBuilder('essay')
        .setParameters({
          param: '%' + essaytitle + '%',
        })
        .where('essay.essaytitle LIKE :param and essay.del = 1')
        .orderBy('essay.created_at', 'DESC') //DESC ASC
        .skip(pagination.currentPage * pagination.pageSize)
        .take(pagination.pageSize)
        .leftJoin('essay.tags', 'tags')
        .leftJoin('essay.user', 'user')
        .andWhere('user.id = :id', { id: userid })
        .select(['essay', 'user', 'tags'])
        .getManyAndCount();
      return res;
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  /**
   * 查询单个短文
   * @param id
   * @returns
   */
  async findOne(id: string) {
    const queryRunner = this.dataSource.createQueryRunner();
    const manager =await queryRunner.manager;  //使用事务 获取manager
    try {
      let cacheKey = `EssayService_findOne_${id}`;
      // 获取缓存
      const cacheData = (await this.cacheManager.get(cacheKey)) as any;
      if (cacheData) {
        console.log(`${cacheKey}有缓存`);
        let view_count = await this.setViewCount(id);
        let cacheRes = {
          ...cacheData,
        };
        if (view_count) {
          cacheRes.view_count = cacheData.view_count + view_count;
        }

        return cacheRes;
      } else {
        console.log(`${cacheKey}没有缓存`);
        const essay = await manager
          .getRepository(EssayEntity)
          .createQueryBuilder('essay')
          .leftJoin('essay.user', 'user')
          .leftJoin('essay.tags', 'tags')
          .where({
            id,
          })
          .select([
            'essay',
            'tags.tagname',
            'user.id',
            'user.headPicture',
            'user.username',
          ])
          .getOne();

        let view_count = essay.view_count + 1;
        await this.dataSource
          .getRepository(EssayEntity)
          .createQueryBuilder('essay')
          .update(EssayEntity)
          .set({
            view_count: view_count,
          })
          .where('id = :id', { id: id })
          .execute();

        // 添加缓存
        await this.cacheManager.set(cacheKey, essay, 1000 * 60 * 60);
        return essay;
      }
    } catch (error) {
      ToolsService.fail(error);
    } finally {
      await queryRunner.release(); //释放

    }
  }

  async setViewCount(id: string) {
    let cacheKey = `essay_view_count_${id}`;
    try {
      let getCount = await this.getViewCount(id);
      let addCount = getCount + 1;
      // 设置缓存
      await this.redisService.set(cacheKey, addCount);
      return addCount;
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  async getViewCount(id: string) {
    let cacheKey = `essay_view_count_${id}`;
    try {
      // 获取缓存
      let essay_view_count = await this.redisService.get(cacheKey);
      if (!essay_view_count) {
        essay_view_count = 0;
      }
      return Number(essay_view_count);
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  async update(id: string, updateEssayDto: UpdateEssayDto) {
    const queryRunner = this.dataSource.createQueryRunner();
    try {
      // 清除整个缓存
      await this.cacheManager.reset();
      const manager = await queryRunner.manager; //使用事务
      const essay = await manager
        .getRepository(EssayEntity)
        .createQueryBuilder('essay')
        .where('essay.id = :id', {
          id: id,
        })
        .getOne();

      if (!essay) {
        throw new Error('短文不存在');
      }
      essay.id = id;
      if(updateEssayDto.essaytitle){
        essay.essaytitle = updateEssayDto.essaytitle;
      }
      if(updateEssayDto.content){
        essay.content = updateEssayDto.content;
      }
      if(typeof  updateEssayDto.watermarking == 'boolean'){
        essay.watermarking = updateEssayDto.watermarking;
      }
      if(updateEssayDto.view_count){
        essay.view_count = updateEssayDto.view_count;
      }
      
      
     await manager.save(essay);
      return essay.id;
    } catch (error) {
      ToolsService.fail(error);
    } finally {
      await queryRunner.release(); //释放连接
    }
  }

  /**
   * 软删除
   * @param id
   */
  async remove(id: string) {
    try {
      // 清除整个缓存
      await this.cacheManager.reset();
      await this.dataSource
        .getRepository(EssayEntity)
        .createQueryBuilder('essay')
        .update(EssayEntity)
        .set({
          del: 1,
        })
        .where('id = :id', { id: id })
        .execute();
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  /**
   * 批量恢复
   * @param ids
   */
  async batchRecovery(ids: string[]) {
    try {
      // 清除整个缓存
      await this.cacheManager.reset();
      await this.dataSource
        .getRepository(EssayEntity)
        .createQueryBuilder()
        .update(EssayEntity)
        .set({
          del: 0,
        })
        .where({
          id: In(ids),
        })
        .execute();
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  /**
   * 销毁
   * @param id
   */
  async destroy(id: string) {
    try {
      // 清除整个缓存
      await this.cacheManager.reset();
      await this.dataSource
        .createQueryBuilder(EssayEntity, 'essay')
        .delete()
        .from(EssayEntity)
        .where('id = :id', { id: id })
        .execute();
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  /**
   * 批量销毁
   * @param ids
   */
  async batchDestroy(ids: string[]) {
    try {
      // 清除整个缓存
      await this.cacheManager.reset();
      await this.dataSource
        .getRepository(EssayEntity)
        .createQueryBuilder()
        .delete()
        .from(EssayEntity)
        .whereInIds(ids)
        .execute();
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  async addTag(addTagDto: AddTagDto) {
    const queryRunner = this.dataSource.createQueryRunner();
    try {
      // 清除整个缓存
      await this.cacheManager.reset();
      const manager = await queryRunner.manager; //使用事务
      const essay = await manager
        .getRepository(EssayEntity)
        .createQueryBuilder('essay')
        .where('essay.id = :id', {
          id: addTagDto.essayId,
        })
        .getOne();
      if (!essay) {
        throw new Error('文章不存在');
      }

      if (addTagDto.tagIds.length > 0) {
        const tags = [];
        for (let i = 0; i < addTagDto.tagIds.length; i++) {
          const listOne = await manager
            .getRepository(TagEntity)
            .createQueryBuilder('tag')
            .where('tag.id = :id', {
              id: addTagDto.tagIds[i],
            })
            .getOne();

          if (!listOne) ToolsService.fail('书签id不存在');
          tags.push(listOne);
        }
        const essayEntity = new EssayEntity();
        essayEntity.id = addTagDto.essayId;
        essayEntity.tags = tags;
        await manager.save(essayEntity);
        return '添加成功';
      } else {
        const essayEntity = new EssayEntity();
        essayEntity.id = addTagDto.essayId;
        essayEntity.tags = [];
        await manager.save(essayEntity);
        return '添加成功';
      }
    } catch (error) {
      ToolsService.fail(error);
    } finally {
      await queryRunner.release(); //释放连接
    }
  }

  async findOwnerTags(essayId: string) {
    try {
      const essay = await this.essayRepository
        .createQueryBuilder('essay')
        .where('essay.id = :id', { id: essayId })
        .leftJoin('essay.tags', 'tags')
        .select(['essay', 'tags'])
        .getOneOrFail();
      return essay.tags;
    } catch (error) {
      ToolsService.fail(error);
    }
  }

  async pinned(essayId: string, status: number) {
    try {
      // 清除整个缓存
      await this.cacheManager.reset();
      await this.dataSource
        .getRepository(EssayEntity)
        .createQueryBuilder()
        .update(EssayEntity)
        .set({
          status: status,
        })
        .where({
          id: essayId,
        })
        .execute();
    } catch (error) {
      ToolsService.fail(error);
    }
  }
}
